home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / x11 / tuner / getx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-16  |  24.3 KB  |  906 lines

  1. /*    getx . c
  2. #
  3. %    Copyright (c)    Lawrence Berkeley Laboratory
  4. %
  5. %    Elastic Control Panel (Editing) & X Extension
  6. % Author:    Jin Guojun - LBL    Mon, Apr 1, 1991
  7. */
  8.  
  9. #include "tuner.h"
  10.  
  11. #ifndef    ExTITLE
  12. #define    ExTITLE    "socket"
  13. #endif
  14. #ifndef    DEF_TITLE
  15. #define    DEF_TITLE    "Standard Input"
  16. #endif
  17. #ifndef    KEEP_WIN_STILL
  18. #define    KEEP_WIN_STILL    8
  19. #endif
  20. #ifndef    XLOGO
  21. #define    XLOGO    "./getxe.logo"
  22. #endif
  23.  
  24. /* must be able to fit 3 * log2 (MAXIMUM_LEVELS) bits in a 32 bit word */
  25.  
  26. #ifndef    DEFAULT_LEVELS
  27. #define DEFAULT_LEVELS    240
  28. #endif
  29. #define MAXIMUM_LEVELS    1024
  30. #define    isame    !strcmp
  31. extern    void    update_pic();
  32. #ifndef    HIPS2_HF
  33. char    *Progname;
  34. #endif
  35.  
  36. /* Make SysV macros map to BSD macros */
  37. #ifndef _tolower
  38. #define _tolower tolower
  39. #define _toupper toupper
  40. #endif
  41.  
  42. /*    Global variables    */
  43.  
  44. static    char     *Help_message_getx =    "\
  45. If start with -T, press CTRL + any Button to show PANEL\n\
  46. multiple frame HIPS or FITS image will not be forked\n\n\
  47. button:      LEFT            MIDDLE           RIGHT\n\n\
  48. alone :  value+coord      toggle-zoom\n\
  49. +SHIFT:    Magnify        zoom-shift          Shrink\n\n\
  50. +CTRL :    moving objects\n\
  51. The # key (1-9) for magnifing scale\n\
  52. for multiple frame image from standard input, use '+' key\
  53. to go forward, and '-' key to go backward one frame\n\
  54. press 'q' key in an image window to quit that image\n\
  55. For more information: see man tuner",
  56.     **infnames, *display_name, *window_geometry, *vis_type,
  57.     *title_str = DEF_TITLE, *svport;
  58.  
  59. static    bool    STS, fforward, nofork, regular_rle, still_win,
  60.         vflag, aflag, bin_flag, mono_flag, iflag;
  61.  
  62. extern    int    num_images, row_dpy_mode, shared_cmap, stingy_flag;
  63.  
  64. static struct {
  65.     CONST_DECL char    *string;
  66.     int        type;
  67. }  visual_type_table[] =    {
  68.     { "staticgray",    StaticGray    },
  69.     { "grayscale",    GrayScale    },
  70.     { "staticgrey",    StaticGray    },
  71.     { "greyscale",    GrayScale    },
  72.     { "staticcolor", StaticColor    },
  73.     { "pseudocolor", PseudoColor    },
  74.     { "truecolor",    TrueColor    },
  75.     { "directcolor", DirectColor    }
  76. };
  77.  
  78. #define    basic_alist1    \
  79.     &window_geometry, &aflag,    \
  80.     &bin_flag, &mono_flag,    \
  81.     &display_gamma,    \
  82.     &row_dpy_mode,    \
  83.     &flip_book, &flip_book_frams_sec,\
  84.     &specified_levels, &OsameI
  85. #define    basic_alist2    \
  86.     &shared_cmap, ®ular_rle,    \
  87.     &stingy_flag, &STS,    \
  88.     &title_str, &verbose, &DEBUGANY
  89.  
  90. #ifdef    FREE_PORT_CHIOCE
  91. #define    basic_alist    basic_alist1, &svport, basic_alist2
  92. #else
  93. #define    basic_alist    basic_alist1, basic_alist2
  94. #endif
  95.  
  96. arg_fmt_list_string    arg_list[] =    {
  97.     {"-d", "%s", No, 1, 1, "display name <host[:x.y]>"},
  98.     {"-f", "%b", True, 1, 0, "run on foreground"},
  99.     {"-i", "%1 %D", 1.0, 2, 1, "gamma of image. (default 1.0)"},
  100.     {"-I", "%2 %D", 1.0, 2, 1,
  101.         "gamma: specify gamma of display image was computed for"},
  102.     {"-N", "%d", MAX_IMAGE_PTRS, 1, 1, "Number of images"},
  103.     {"-T", "%b", True, 1, 0, "use Tuner panel"},
  104.     {"-v", "%1 %s", No, 2, 1,
  105.         "vis_type: specify Visual type to be used\n\
  106.             (string or int, 0 to 5)"},
  107.  
  108.     {"-=", "%s", NULL, 1, 1, "window_geometry:\n\
  109.             Specify window geometry (but min size set by file)."},
  110.     {"-a", "%b", True, 1, 0, "Do not dither"},
  111.     {"-b", "%b", True, 1, 0, "binary (black and white)"},
  112.     {"-B", "%b", True, 1, 0, "monochrome"},
  113.     {"-g", "%D", 1.5, 1, 1,    "gamma for display. (default 1.5)"},
  114.     {"-j", "%b", True, 1, 0, "display images line by line"},
  115.     {"-m", "%1 %d", 30, 2, 0, "frames/sec:    run movie [set speed]"},
  116.     {"-n", "%d", DEFAULT_LEVELS, 1, 1,
  117.         "number of colors to dither colormaps"},
  118.     {"-O", "%b", False, 1, 0,
  119.         "Output 3-channels RLE. Otherwise, output same as input"},
  120. #ifdef    FREE_PORT_CHIOCE
  121.     {"-P", "%s", No, 1, 1, "Port # for Ext X server"},
  122. #endif
  123.     {"-p", "%b", False, 1, 0, "perform no-shared colormap"},
  124.     {"-r", "%b", True, 1, 0, "regular RLE coordinate"},
  125.     {"-S", "%b", True, 1, 0, "Slow mode for remote display"},
  126.     {"-s", "%b", True, 1, 0,
  127.         "slower start, but get fixed color for panel"},
  128.     {"-t", "%s", NULL, 1, 0, "title on image windows"},
  129.     {"-V", "%b", True, 1, 0, "Verbose some information; High level debug"},
  130.     {"-D", "%d", 1, 1, 0, "Debug level: turn on kernel debug"},
  131.     {"input:    Any Image file. Use stdin if none specified", "0",
  132.         0, 0, 0, "\nEnd of options"},    NULL    },
  133.     *b_arg_list = arg_list + 7;
  134. /*
  135. %    getx will also read picture comments from the input file to
  136. %        determine the image gamma.  These are
  137. %
  138. %    image_gamma=    gamma of image (equivalent to -i)
  139. %    display_gamma=    gamma of display image was computed for.
  140. %
  141. %    Any command line arguments override the values in the file.
  142. %
  143. % Outputs:    Puts image on screen.
  144. % Assumptions:    Input file is converted to RLE format.
  145. */
  146.  
  147. void
  148. init_img_flag(img)
  149. Image*    img;
  150. {
  151.     img->binary_img = bin_flag;
  152.     img->mono_img = mono_flag | bin_flag;
  153.     if (img->mono_img)    {
  154.         img->color_dpy = False;
  155.         img->dpy_channels = 1;
  156.     }
  157.     img->dither_img = !aflag;
  158.     if (!img->lvls)
  159.         img->lvls = specified_levels;
  160. }
  161.  
  162. ColorImageInfo(img, top)
  163. image_information*    img;
  164. {
  165. Boolean first = 1;
  166. int    lx=GetGray(img->dpy, img->colormap, img->entries, 96), ly=GetCloseColor
  167.     (img->dpy, img->colormap, img->entries, NULL, 192, 248, 160);
  168.  
  169.     set_left_ptr_cursor(img->window);
  170.  
  171.     MapPixWindow(img, top, lx < 0 ? MGray : lx);
  172.     XSetForeground(img->dpy, img->gc, ly < 0 ? White : ly);
  173.     lx = ly = 0;
  174.     Loop    {    /* loop until button released */
  175.     Window foo,poo;
  176.     int rx, ry, x, y;
  177.     unsigned int mask;
  178.  
  179.     if (XQueryPointer(img->dpy, img->window, &foo, &poo, &rx, &ry,
  180.         &x, &y, &mask))    {
  181.         if (!(mask&(Button1Mask | Button3Mask)))
  182.             break; /* released */
  183.         mask = abs(img->mag_fact);
  184. #ifndef    SCROLLBAR_on_CANVAS
  185.         x += img->x,    y += img->y;
  186. #endif
  187.         if (img->mag_fact > 0)
  188.             x /= mask,    y /= mask;
  189.         else    x *= mask,    y *= mask;
  190.         x += img->mag_x;    y += img->mag_y;
  191.             /* wait for new pixel */
  192.         if ((first || x != lx || y != ly) &&
  193.             (x >= 0 && x < img->w &&
  194.              y >= 0 && y < img->h)) {
  195.             DrawPixWindow(img, x, y, regular_rle);
  196.             first = 0;  lx = x;  ly = y;
  197.         }
  198.     } else    break;
  199.     }
  200.     set_circle_cursor(img->window);
  201.     UnmapPixWindow(img);
  202. }
  203.  
  204.  
  205. main(argc, argv)
  206. int    argc;
  207. char*    *argv;
  208. {
  209. int    nf, n_malloced, using_stdin,
  210.     flip_book=0, flip_book_frams_sec=30,
  211.     visual_type= -1;
  212. double    image_gamma=0.0;    /* default gamma for image */
  213.  
  214. Progname = argv[0];    OsameI = shared_cmap = True;
  215.  
  216.     if ((nf=parse_argus(&infnames, argc, argv, arg_list,
  217.         &display_name, &nofork,
  218.         &iflag, &image_gamma,
  219.         &iflag, &image_gamma,
  220.         &n_malloced, &tuner_flag,
  221.         &vflag, &vis_type,
  222.         basic_alist)) < 0)
  223. #ifdef    IGNORE_PARSE_ERROR
  224.     if (nf < 0)    nf = 0;
  225. #else
  226.     exit(1);
  227. #endif
  228.     regular_rle |= flip_book;
  229.     display_gamma += flip_book;
  230.     if (!shared_cmap)
  231.         precision = 32;    /* better for CFM_SCF    */
  232.     still_win = n_malloced < KEEP_WIN_STILL;
  233.  
  234.     if (using_stdin = !nf)    {    /* no input    */
  235.         io_test(fileno(stdin),
  236.         if (!freopen(XLOGO, "rb", stdin)) prgmerr('f', XLOGO);
  237.         if (OsameI & shared_cmap)    OsameI = shared_cmap = 0);
  238.         nf++;
  239.     }
  240.     /*    open the display    */
  241.  
  242.     if (display_name == NULL || *display_name == '\0')
  243.     display_name = getenv("DISPLAY");
  244.     if ((Dpy=XOpenDisplay(display_name)) == NULL)
  245.     prgmerr(1, "Cant open display %s\n", display_name);
  246.  
  247.     /* Work around bug in X11/NeWS server colormap allocation. */
  248.     if (isame("X11/NeWS - Sun Microsystems Inc.", ServerVendor(Dpy)) &&
  249.         VendorRelease(Dpy) == 2000)
  250.     no_color_ref_counts = True;
  251.  
  252. #if    defined    HIPS2_HF | defined HIPS_IMAGE
  253.     hipserrprt = hipserrlev = HEL_SEVERE;
  254. #endif
  255.  
  256.     if (specified_levels < 1)
  257.         specified_levels = DEFAULT_LEVELS; /* default starting point */
  258.     if (specified_levels > MAXIMUM_LEVELS)
  259.         specified_levels = MAXIMUM_LEVELS;
  260.     pic = (Image**)ZALLOC(n_malloced, sizeof(*pic), "img_info");
  261.  
  262.     if (vflag) {
  263.     if (isdigit(vis_type[0]))
  264.         visual_type = atoi(vis_type);
  265.     else {
  266.     register char    *ptr = vis_type;
  267.     register int    i;
  268.     visual_type = 9999;
  269.  
  270.         do    if (isupper(*ptr)) *ptr = _tolower(*ptr);
  271.         while (*ptr);
  272.  
  273.         for (i = 0; i < COUNT_OF (visual_type_table); i++) {
  274.         if (isame(visual_type_table[i].string, vis_type)) {
  275.             visual_type = visual_type_table[i].type;
  276.             break;
  277.         }
  278.         }
  279.     }
  280.  
  281.     if (visual_type < 0 || visual_type > 5) {
  282.         message("Bad visual type %s, ignoring request\n", vis_type);
  283.         visual_type = -1;
  284.     }
  285.     }
  286.  
  287.     cmn_hd.visual_class = visual_type;
  288.     init_img_info(&cmn_hd, Dpy, RLE, -1);
  289.     find_appropriate_visual(&cmn_hd);    /* for global set up */
  290.     cmn_hd.pixmap_failed = stingy_flag && !flip_book;
  291.     if (iflag==2 && image_gamma)    cmn_hd.gamma = 1. / image_gamma;
  292.     else if (iflag==1)    cmn_hd.gamma = image_gamma;
  293.     if (STS)    start_fast = False;
  294.     CreateColorTuner(Dpy, Monitor[1].dpy, &cmn_hd, tuner_flag, No, STS);
  295.     VCTEntry >>= flip_book;
  296.  
  297.     {    register int    i;
  298.     for (i=0; i < nf; i++)    {
  299.     if (!using_stdin && strcmp(infnames[i], "-")) {
  300.         cmn_hd.name = infnames[i];
  301.         cmn_hd.IN_FP = rle_open_f_noexit("getx", cmn_hd.name, "r");
  302.         if (!cmn_hd.IN_FP)    {
  303.             prgmerr(nf==1, cmn_hd.name);
  304.             continue;
  305.         }
  306.     } else    cmn_hd.name = title_str;
  307.     if (tuner_flag && i)
  308.         LoadImage(cmn_hd.IN_FP, pic+num_images+i-1, cmn_hd.name);
  309.     else    nofork |= LoadGXImage(&num_images, &cmn_hd, &pic, flip_book,
  310.                 window_geometry, still_win) && using_stdin;
  311.     }
  312.     }
  313.     if (!num_images)
  314.         prgmerr(1, "no image can be displayed");
  315.     if (!tuner_flag)    {
  316.     InfoWin = CreatePanel(10, 10, 512, 256, "Information", Monitor, NULL);
  317.     MGray = GetGray(Dpy, Monitor[0].cmap, ncolors, 64);
  318.     XSetWindowBackground(Dpy, InfoWin->win, MGray);
  319.     }    /* else
  320.     CreateColorTuner(Dpy, Monitor[1].dpy, &cmn_hd, tuner_flag, Yes, STS);
  321. */
  322. #ifdef unix
  323.     if (!nofork) {
  324.     if (fork()==0) {
  325.     /* Set process group to avoid signals under sh. */
  326.         setpgrp(
  327. #ifndef SYS_V_SETPGRP
  328.             0, getpid()
  329. #endif
  330.                     );
  331.         close(0);    close(1);
  332.         setsid();    /*    close(2);    */
  333.         update_pic(flip_book, flip_book_frams_sec,
  334.                 MAX(num_images,n_malloced));
  335.     }
  336.     else    exit(0);
  337.     }
  338.     else
  339. #endif
  340.     update_pic(flip_book, flip_book_frams_sec, MAX(num_images,n_malloced));
  341.     XCloseDisplay(Dpy);
  342. }
  343.  
  344.  
  345. /*
  346. * Track events & redraw image when necessary.
  347. */
  348.  
  349. action_flip_forward(start, img_info, flip_book_udelay, n, mask, event, found_event)
  350. image_information    **img_info;
  351. int    flip_book_udelay, n;
  352. unsigned long    mask;
  353. XEvent *event;
  354. Boolean *found_event;
  355. {
  356. image_information    *img;
  357.     if (mask) *found_event = False;
  358.  
  359.     if (start == n-1)
  360.     start = 0;
  361.     while(start < n) {
  362.     set_timer(flip_book_udelay);
  363.     img = img_info[start++];
  364.     handle_exposure(img, Draws, 0, 0, img->w, img->h, img->h);
  365.     if (img->IN_FP != stdin && flip_book_udelay) /* as fast as possible */
  366.         XStoreName(img->dpy, img->frame, img->title);
  367.     XFlush(img->dpy);
  368.     if (mask && XCheckMaskEvent(img->dpy, mask, event))    {
  369.         *found_event = True;
  370.         break;
  371.     }
  372.     wait_timer();
  373.     }
  374.     if (mask && *found_event && start < n)
  375.     return    start;
  376.     else    return    --start;
  377. }
  378.  
  379. action_flip_backward(start, img_info, flip_book_udelay, n, mask, event, found_event)
  380. image_information    **img_info;
  381. int    flip_book_udelay, n;
  382. unsigned long    mask;
  383. XEvent    *event;
  384. Boolean    *found_event;
  385. {
  386. image_information    *img;
  387.     if (mask) *found_event = False;
  388.  
  389.     if (!start++)
  390.     start = n;
  391.     while (start--)    {
  392.     set_timer(flip_book_udelay);
  393.     img = img_info[start];
  394.     handle_exposure(img, Draws, 0, 0, img->w, img->h, img->h);
  395.     if (img->IN_FP != stdin && flip_book_udelay) /* as fast as possible */
  396.         XStoreName(img->dpy, img->frame, img->title);
  397.     XFlush(img->dpy);
  398.     if (mask && XCheckMaskEvent(img->dpy, mask, event))    {
  399.         *found_event = True;
  400.         break;
  401.     }
  402.     wait_timer();
  403.     }
  404.     if (mask && *found_event)
  405.     return    start;
  406.     else return    start + 1;
  407. }
  408.  
  409. action_flip_book_cycle(start, img_info, n, flip_forward, flip_book_udelay)
  410. image_information    **img_info;
  411. int    n, flip_book_udelay;
  412. Boolean    flip_forward;
  413. {
  414. int    found_event;
  415. XEvent    event;
  416.  
  417.     do {
  418.     start = (* (flip_forward ? action_flip_forward : action_flip_backward))
  419.     (start, img_info, flip_book_udelay, n, ButtonPressMask|KeyPressMask,
  420.         &event, &found_event);
  421.     XSync(img_info[0]->dpy, False);
  422.     } while (!found_event);
  423.     return    start;
  424. }
  425.  
  426.  
  427. /* define what to do on mouse buttons */
  428. static int button_action[3][3] = {
  429.     ACTION_MAGNIFY,        ACTION_PIXEL_INFO,        ACTION_OBJECT,
  430.     ACTION_PAN,        ACTION_SWITCH_MAG_MODE,        ACTION_TUNER,
  431.     ACTION_UNMAGNIFY,    ACTION_SUB_WINDOW,        ACTION_TUNER
  432.     };
  433.  
  434. /* equivalent to flip_book mouse buttons on flip_action[3][2] =    {
  435.     ACTION_FLIP_FORWARD,    ACTION_CYCLE,
  436.     ACTION_FLIP_STEP,    ACTION_FLIP_SPEED,
  437.     ACTION_FLIP_BACKWARD,    ACTION_CYCLE_TO_AND_FRO
  438.     };
  439. */
  440.  
  441. static void
  442. update_pic(flip_book, flip_book_frams_sec, maxRLE_images)
  443. Boolean    flip_book;
  444. int    flip_book_frams_sec;
  445. {
  446. XEvent event;
  447. int    i, action, cur_img=0, found_event, sb=0, Tuner_act=-1;
  448. register image_information*    img=NULL;
  449.  
  450. #define    n    num_images
  451.  
  452.     /* variables to use for flip_book mode */
  453. Boolean    flip_forward = True;
  454. Window    dead_window;
  455. int    flip_book_udelay=0, flip_frame=0;
  456.  
  457.     if (tuner_flag)
  458.         histinfo.histp = pic[0]->hist,    DrawPanel();
  459. #ifdef    X_Extender
  460.     {
  461.     char    pn[16];
  462.     int    ret_port = x_extender_init(svport, 0, 0);
  463.     sprintf(pn, "tcp port # = %d", ret_port);
  464.     img = pic[0];
  465.     XDrawString(img->dpy,img->window,img->gc,
  466.             img->w-144, img->h-8, pn, strlen(pn));
  467.     if (ret_port < 0)    goto    quit_server;
  468. #ifdef    GETXE_RTP
  469. #define    SERVERS    2
  470.     x_extender_init(0, 1, 0);
  471. #else
  472. #define    SERVERS    1
  473. #endif
  474.     img = NULL;
  475.     }
  476. #endif
  477.  
  478.     while (n) {
  479.     image_information **    rpic=pic;
  480.  
  481. #ifdef    X_Extender
  482.     while (!XEventsQueued(rpic[0]->dpy, QueuedAfterFlush))
  483.     for (i=0; i < SERVERS; i++)    {
  484.     register FILE*    sfp = x_extender(i);
  485.         if (sfp && ~(int)sfp)    {
  486. # ifdef    SOCKET_DEBUG
  487.         while (!feof(sfp))
  488.             putc(fgetc(sfp), stderr);
  489. # else
  490.         title_str = ExTITLE;
  491.         if (i = get_arg_list(&infnames))
  492.             parse_argus(NULL, i, infnames, b_arg_list, basic_alist);
  493.         cmn_hd.name = title_str;
  494.         if (tuner_flag)    {
  495.             if ((i=LoadImage(sfp, rpic+n, cmn_hd.name)) == FileLoad)    {
  496.             if (img)    img->active = False;
  497.             img = rpic[n++];
  498.             img->active++;
  499.             } else if (!i)    goto    cleanudp;
  500.         } else if (LoadGXImage(&num_images, &cmn_hd, &pic,
  501.                 flip_book, window_geometry, still_win) < 0)
  502. cleanudp:    {    char    sbuf[256];
  503.             while (read(fileno(sfp), sbuf, sizeof(sbuf)) > 0);
  504.         } else    rpic = pic;
  505. # endif
  506.         }
  507.     }
  508. #endif
  509.     XNextEvent(rpic[0]->dpy, &event);
  510.  
  511.     if (flip_book){    /* all windows are the same! */
  512.         flip_book_udelay =
  513.             (flip_book_frams_sec) ? 1000000 / flip_book_frams_sec : 0;
  514.         img = rpic[flip_frame];
  515.     } else {
  516.         cur_img = WhichImage(event.xany.window, rpic, n);
  517.         if (cur_img < 0)
  518.             img = NULL;
  519.         else    {
  520.             for (i=n; i--;)
  521.                 if (rpic[i]->active)
  522.                 rpic[i]->active = 0;
  523.             img = rpic[cur_img];
  524.             img->event = &event;
  525.             img->active++;
  526.         }
  527.     }
  528.     if (!img && event.type!=Expose && event.type!=EnterNotify)
  529.         continue;
  530.  
  531.     switch (event.type) {
  532.  
  533.     case ButtonPress:
  534.         i = event.xbutton.button - Button1;
  535.         if (i < 0 || i > COUNT_OF(button_action))
  536.         action = ACTION_DEFAULT;
  537.         else{
  538.         register int j=event.xbutton.state & (ShiftMask | ControlMask);
  539.         if (j > 2)    j = 2;
  540.         else        j ^= tuner_flag | !regular_rle;
  541.         action = button_action[i][j];
  542.         }
  543.  
  544.         switch (action)    {
  545.  
  546.         case ACTION_PIXEL_INFO:/*    case ACTION_CYCLE:    */
  547.         /* cycle in the current (flip_forward) direction */
  548.         if (flip_book) {
  549.             flip_frame = action_flip_book_cycle
  550.             (cur_img, rpic, n, flip_forward, flip_book_udelay);
  551.             img = rpic[flip_frame];
  552.         }
  553.         else if (!(img->parts && (sb=OnScrollBar(img->parts,
  554.             &event.xbutton))) && img->scan_data)
  555.             ColorImageInfo(img, event.xbutton.y
  556. #ifdef    SCROLLBAR_on_CANVAS
  557.         - img->y
  558. #endif
  559.                 > img->resize_h>>1);
  560.         continue;
  561.         case ACTION_SUB_WINDOW:/*    case ACTION_CYCLE_TO_AND_FRO:    */
  562.         if (!flip_book)    {
  563.             if (!tuner_flag)    continue;
  564.             set_left_ptr_cursor(img->window);
  565.             img->tmp_offset = fontHeight + IIMargin;
  566.         TrackSubWin(img, &histinfo, event.xbutton.x, event.xbutton.y,
  567.             DrawsRect, CropButton,
  568. #ifdef    SCROLLBAR_on_CANVAS
  569.         img->y);
  570. #else
  571.         0);
  572. #endif
  573.         } else    {
  574.             do {
  575.             cur_img = (*(flip_forward ?
  576.                 action_flip_forward : action_flip_backward))
  577.                 (cur_img, rpic, flip_book_udelay,
  578.                 n, ButtonPressMask | KeyPressMask,
  579.                 &event, &found_event);
  580.             if (!found_event)    {
  581.                 flip_forward = !flip_forward;
  582.                 if (n > 1)
  583.                 flip_forward ? cur_img++ : cur_img--;
  584.             }
  585.             XSync(img->dpy, False);
  586.             }    while(!found_event);
  587.             flip_frame = cur_img;
  588.         }
  589.         continue;
  590.  
  591.         case ACTION_MAGNIFY:/*    case ACTION_FLIP_FORWARD:    */
  592.         if (flip_book) {
  593.             cur_img = action_flip_forward (cur_img, rpic, flip_book_udelay,
  594.                      n, ButtonPressMask|KeyPressMask,
  595.                      &event, &found_event);
  596.             flip_frame = cur_img;
  597.             flip_forward = True;
  598.         }
  599.         else mag_pan(img, action, event.xbutton.x, event.xbutton.y,
  600.             img->mag_fact + 1, stingy_flag);
  601.         continue;
  602.         case ACTION_UNMAGNIFY:/*    case ACTION_FLIP_BACKWARD:    */
  603.         if (flip_book) {
  604.             cur_img = action_flip_backward(cur_img, rpic,
  605.                 flip_book_udelay, n,
  606.                 ButtonPressMask | KeyPressMask,
  607.                 &event, &found_event);
  608.             flip_frame = cur_img;
  609.             flip_forward = False;
  610.         }
  611.         else    mag_pan(img, action, event.xbutton.x, event.xbutton.y,
  612.             img->mag_fact - 1, stingy_flag);
  613.         continue;
  614.         case ACTION_SWITCH_MAG_MODE:/*    case ACTION_FLIP_SPEED:    */
  615.         /* X calls by John Bradley, U of Penn, hacked up by mrf. */
  616.         if (flip_book)    {
  617.         Boolean    first = 1;
  618.         int    height = DisplayHeight(Dpy, Screen) >> 2,/* use DH/4 */
  619.             ly = 0, s = flip_book_frams_sec;
  620.             MapPixWindow(img=rpic[0], True, MGray);
  621.  
  622.             Loop    {    /* loop until button released */
  623.             Window foo,poo;
  624.             int rx, ry, x, y, inc;
  625.             unsigned int mask;
  626.  
  627.             if (XQueryPointer(img->dpy, img->window, &foo, &poo,
  628.                     &rx, &ry, &x, &y, &mask)) {
  629.                 if (!(mask&(Button1Mask|Button2Mask|Button3Mask)))
  630.                 break;    /* released */
  631.  
  632.                 if (first)
  633.                 ly = y;
  634.                 inc = (ly - y) * 100 / height;
  635.  
  636.                 /* wait for new pixel */
  637.                 if ((first || flip_book_frams_sec + inc != s)) {
  638.                 s = flip_book_frams_sec + inc;
  639.                 s = (s < 0) ? 0 : s & 0x7F;
  640.                 DrawSpeedWindow(img, s);
  641.                 first = 0;
  642.                 }
  643.             }
  644.             else    break;
  645.             }
  646.             flip_book_frams_sec = s;
  647.             UnmapPixWindow(img);
  648.         }
  649.         else mag_pan(img, action, event.xbutton.x, event.xbutton.y,
  650.             img->mag_fact, stingy_flag);
  651.         continue;
  652.  
  653.         case ACTION_PAN:/*    case ACTION_FLIP_STEP:    */
  654.         /* step flip_book in current direction. */
  655.         if (flip_book) {
  656. afs:            if (flip_forward) {
  657.             if (flip_frame == n-1)
  658.                 img = rpic[flip_frame=0];
  659.             else    img = rpic[++flip_frame];
  660.             }
  661.             else {
  662.             if (flip_frame < 1)
  663.                 img = rpic[flip_frame = n-1];
  664.             else    img = rpic[--flip_frame];
  665.             }
  666.             handle_exposure(img, Draws, 0, 0, img->w, img->h, img->h);
  667.             XStoreName(img->dpy, img->frame, img->title);
  668.         }
  669.         else    mag_pan(img, action, event.xbutton.x, event.xbutton.y,
  670.             img->mag_fact, stingy_flag);
  671.         continue;
  672.  
  673.         case ACTION_OBJECT:
  674.         if (i=on_superimpose_elem(img, event.xbutton.x, event.xbutton.y))
  675.             superimpose_handle(img, i,
  676.                 event.xbutton.x, event.xbutton.y);
  677.         continue;
  678.  
  679.         case ACTION_TUNER:
  680.         if (tuner_flag && Tuner_act < 0)
  681. tuner_action:        Tuner(rpic, maxRLE_images, &Tuner_act);
  682.         else    XBell(img->dpy, 0);
  683.         default:
  684.         continue;
  685.         }
  686.         break;    /* not reached */
  687.     case EnterNotify:    {    /* an ETA section */
  688.     static    int    last_active = -1;
  689.         if (!tuner_flag)    continue;    /* not ETA */
  690.         if (cur_img==last_active || cur_img<0)
  691.             if (img)    continue; /* enter same window again */
  692.             else    goto    tuner_action;
  693.         else    {
  694.             last_active = cur_img;
  695.             if (img->linearup < 24) {
  696.                 ButtonState(FButton) = img->RGB = ButtonSync;
  697.                 ResetORange(img);
  698.                 img->curve = ETALinear;
  699.             }
  700.             Panel_Image(img, histinfo.lkt);
  701.             Fresh_ImageScreen(img, NULL /* no interpolation */, &i);
  702.         }
  703.     }    continue;
  704.     case Expose:
  705.     if (img && event.xexpose.window==img->window)
  706.         handle_exposure(img, Draws, event.xexpose.x, event.xexpose.y,
  707.                 event.xexpose.width, event.xexpose.height,
  708.                 img->h, tuner_flag);
  709.     else if (tuner_flag)
  710.         Exposure_handler(&event, NULL);
  711.     continue;
  712.  
  713.     case ButtonRelease:
  714.     if (sb)    {
  715. #ifndef    SCROLLBAR_on_CANVAS
  716.         if (img->refresh_pixmap)
  717.         XCopyArea(img->dpy, img->refresh_pixmap, img->window, img->gc,
  718.             img->x, img->y, img->resize_w, img->resize_h, 0, 0);
  719.         else
  720.         XPutImage(img->dpy, img->window, img->gc, img->image,
  721.             img->x, img->y, 0, 0, img->resize_w, img->resize_h);
  722.         if (img->sub_img)    DrawCrop(img, 0, 1);
  723. #    endif
  724.         DrawScrollBars(img->parts, img->parts->scrollbar.type),
  725.         sb = 0;
  726.     }
  727.     continue;
  728.  
  729.     case ConfigureNotify:
  730.     case ResizeRequest:
  731.         ResizeWindow(img, &event);    continue;
  732.     case MotionNotify:
  733.     if (sb)
  734.         SetScrollBar(img->parts,event.xbutton.x,event.xbutton.y,sb-1);
  735.     case LeaveNotify:
  736.     case NoExpose:    continue;
  737.  
  738.     case KeyPress:    {
  739.     char    string[256], *symstr, *XKeysymToString();
  740.     KeySym    keysym;
  741.     XComposeStatus    stat;
  742.     Boolean    shifted_key;
  743.     int    handled_key = keysym,
  744.         length = XLookupString(&event, string, 256, &keysym, &stat);
  745.  
  746.         string[length] = 0;
  747.         symstr = XKeysymToString(keysym);
  748.         shifted_key = event.xkey.state & ShiftMask;
  749.  
  750.         if (length == 1)    {
  751.         i = string[0];
  752.         if ((toupper(i) == 'Q' || i == 3)) /* Qs or ^C */
  753.             break;
  754.         if (isdigit(i))    {
  755.             i = atoi(string);
  756.             if (handled_key == XK_Alt_L || handled_key == XK_Alt_R)
  757.                 i = -i;
  758.             mag_pan(img, ACTION_MAGNIFY, event.xkey.x,
  759.                 event.xkey.y, i, stingy_flag);
  760.         } else    switch(i)    {
  761.         case '+':if (img->img_num>1 && !flip_book) {
  762.         byte*    tp = img->data;
  763.             length = img->w * img->h * img->dpy_channels;
  764.             img->data += length;
  765.             if (!tuner_flag)
  766.                 img->scan_data = img->data;
  767.             if (fforward++) {    /* both kludge plus 1 */
  768.                 if (img->RGB >= img->img_num)
  769.                     goto    fwd_resume;
  770.                 memcpy(tp, img->data, length);
  771.             (img->std_swif)(FI_RLOAD_BUF, img, img->data, OsameI);
  772.             }
  773.             img->RGB++;
  774.             DumpScan_to_dpy(img);
  775.  
  776. fwd_resume:        img->data = tp;
  777.             if (!tuner_flag)
  778.                 img->scan_data = img->data;
  779.         }    break;
  780.         case '-':
  781.             if (fforward) {
  782.                 fforward = 0;
  783.                 img->RGB--;
  784.                 DumpScan_to_dpy(img);
  785.             }
  786.             break;
  787.         case 'b':    /* back and forth mode */
  788.             if (flip_book) {
  789.             do {
  790.                 cur_img = (* (flip_forward ?
  791.                 action_flip_forward : action_flip_backward))
  792.                 (cur_img, rpic, flip_book_udelay,
  793.                 n, ButtonPressMask | KeyPressMask,
  794.                 &event, &found_event);
  795.                 if (!found_event)    {
  796.                 flip_forward = !flip_forward;
  797.                 if (n > 1)
  798.                     cur_img = (flip_forward) ? cur_img++ : cur_img--;
  799.                 }
  800.                 XSync(img->dpy, False);
  801.             } while(!found_event);
  802.             flip_frame = cur_img;
  803.             }
  804.             break;
  805.         case 'c':
  806.         case 'C':
  807.             if (flip_book) {
  808.             flip_forward = (string[0] == 'c');
  809.             flip_frame = action_flip_book_cycle
  810.                 (flip_frame, rpic, n, flip_forward, flip_book_udelay);
  811.             img = rpic[flip_frame];
  812.             }
  813.             break;
  814.         case ' ':
  815.             if (flip_book)    goto    afs;
  816.             break;
  817.         case 'h':
  818.         case 'H':
  819.             Toggle_Info(Help_message_getx);
  820.             break;
  821.         case 'i':
  822.         case 'I':
  823.         /*    Install/deinstall colormap.
  824.         *    Should only do this if no window manager running,
  825.         *    but that's hard to tell.  Let user deal with it...
  826.         */
  827.             if (img->colormap)
  828.             if (string[0] == 'i')
  829.                 XInstallColormap(img->dpy, img->colormap);
  830.             else    XUninstallColormap(img->dpy, img->colormap);
  831.             break;
  832.  
  833.         default:
  834.             handled_key = False;
  835.         }
  836.         }    else    handled_key = False;
  837.  
  838.         DPRINTF(stderr, "%s %x, %s String '%s' - %d\n", symstr, keysym,
  839.         (shifted_key) ? "shifted" : "unshifted", string, length);
  840.  
  841.         if (handled_key > 0) {
  842.         /* GACK! the F28-34 keysyms are for the Suns!    */
  843.         /* on the DECs they are Left Right Up and Down w/ShiftMask */
  844.         /* on the ardent they are KP_4 KP_6 KP_8 KP_2 w/ShiftMask */
  845.         /* insert your favorite shifted arrow keysyms here    */
  846.  
  847.         if (isame(symstr, "Left") || isame(symstr, "F30"))
  848.             i = shifted_key ? 0 : img->w>>2,
  849.             length = img->h >> 1;
  850.         else if (isame(symstr, "Up") || isame(symstr, "F28"))
  851.             i = img->w >> 1,
  852.             length = shifted_key ? 0 : img->h>>2;
  853.         else if (isame(symstr, "Right") || isame(symstr, "F32"))
  854.             i = shifted_key ? img->w-1 : img->w * 3 >> 2,
  855.             length = img->h>>1;
  856.         else if (isame(symstr, "Down") || isame(symstr, "F34"))
  857.             i = img->w >> 1,
  858.             length = shifted_key ? img->h-1 : img->h * 3 >> 2;
  859.         else    continue;
  860.         mag_pan(img, ACTION_PAN, i, length, img->mag_fact, stingy_flag);
  861.         }
  862.         continue;
  863.     }
  864.     case MapNotify:
  865.         if (event.xunmap.window == img->frame)
  866.             XUnmapWindow(img->dpy, img->icn_window);
  867.         else if (event.xunmap.window == img->icn_window)
  868.             XUnmapWindow(img->dpy, img->frame);
  869.         continue;
  870.     case UnmapNotify:
  871.         if (event.xunmap.window == img->frame)    {
  872.             LoadIcon(img);
  873.             XMapWindow(img->dpy, img->icn_window);
  874.         }
  875.         else if (event.xunmap.window == img->icn_window)
  876.             XMapWindow(img->dpy, img->frame);
  877.         continue;
  878.     case MappingNotify:
  879.         XRefreshKeyboardMapping(&event.xmapping);
  880.         continue;
  881.  
  882.     default:    prgmerr(0, "Event type %0X?", event.type);
  883.     continue;
  884.     }
  885.  
  886.     dead_window = DestroyColorImage(img);    /* exit this window */
  887.  
  888.     if (--n) {    /* pack imgs in there good */
  889.         for (;cur_img < n; cur_img++)
  890.         rpic[cur_img] = rpic[cur_img+1];
  891.         rpic[cur_img] = NULL;
  892.     }
  893.     else    if (!tuner_flag)    {
  894. #ifdef    X_Extender
  895. quit_server:    XBell(Dpy, 0);
  896.         Toggle_Info("\n                Quit Extended X Server");
  897.         sleep(5);
  898.         XBell(Dpy, 0);
  899. #endif
  900.         break;
  901.     }
  902.     if (rpic[0]->window == dead_window)
  903.         break;    /* only for safety of movies. Not really reached */
  904.     }
  905. }
  906.